package top.huanyv.tools.utils;

import top.huanyv.tools.bean.Digest;

import java.io.*;

public class FileUtil {
    /**
     * 拷贝一个文件夹
     *
     * @param source 源文件夹
     * @param target 目标文件夹
     * @return 是否成功
     */
    public static boolean copyDir(String source, String target) {
        return copyDir(new File(source), new File(target));
    }

    public static boolean copyDir(File source, File target) {
        // 目标目录 加上 源文件夹名称
        target = new File(target.getAbsolutePath() + File.separator + source.getName());
        return copyDirContent(source, target);
    }

    /**
     * 拷贝目录下的所有文件 TODO 增加忽略选项
     *
     * @param source 源目录
     * @param target 目标目录
     * @return 是否成功
     */
    public static boolean copyDirContent(String source, String target) {
        return copyDirContent(new File(source), new File(target));
    }

    public static boolean copyDirContent(File source, File target) {
        // 查看源目录是否存在并且是一个dir
        if (!source.exists() || !source.isDirectory()) {
            return false;
        }
        // 目标目录是否存在
        if (!target.exists()) {
            target.mkdirs();
        }
        // 获取源目录下的所有文件列表
        File[] files = source.listFiles();
        for (File file : files) {
            if (file.isFile()) {
                // 如果是文件，拷贝过去
                copyFile(file, target);
            }
            if (file.isDirectory()) {
                // 获取目标目录
                File targetFile = new File(target.getAbsolutePath() + File.separator + file.getName());
                // 创建文件夹
                if (!targetFile.exists()) {
                    targetFile.mkdirs();
                }
                // 递归
                copyDirContent(file, targetFile);
            }
        }
        return true;
    }


    /**
     * 拷贝文件
     *
     * @param source 源文件
     * @param target 目标文件或目录
     * @return 是否成功
     */
    public static boolean copyFile(String source, String target) {
        return copyFile(new File(source), new File(target));
    }

    public static boolean copyFile(File source, File target) {
        // 源文件必须是个文件
        if (!source.isFile()) {
            return false;
        }
        // 如果目标是个目录，使用源文件的名称
        if (target.isDirectory()) {
            String fileName = source.getName();
            target = new File(target.getAbsolutePath() + File.separator + fileName);
        }
        BufferedInputStream input = null;
        BufferedOutputStream output = null;
        try {
            input = new BufferedInputStream(new FileInputStream(source));
            output = new BufferedOutputStream(new FileOutputStream(target));
            int len = 0;
            byte[] buffer = new byte[1024 * 10];
            while ((len = input.read(buffer)) != -1) {
                output.write(buffer, 0, len);
            }
            output.flush();
        } catch (IOException e) {
//            e.printStackTrace();
            return false;
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (output != null) {
                try {
                    output.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return true;
    }

    /**
     * 删除一个文件夹中的所有内容
     *
     * @param target 目标文件夹
     * @return 是否成功
     */
    public static boolean deleteDirContent(String target) {
        return deleteDirContent(new File(target));
    }

    public static boolean deleteDirContent(File target) {
        File[] files = target.listFiles();
        for (File file : files) {
            if (file.isFile()) {
                file.delete();
            }
            if (file.isDirectory()) {
                deleteDirContent(file);
                file.delete();
            }
        }
        return true;
    }

    /**
     * 删除一个文件夹
     *
     * @param target 目标文件夹
     * @return 是否成功
     */
    public static boolean deleteDir(String target) {
        return deleteDir(new File(target));
    }

    public static boolean deleteDir(File target) {
        if (!target.isDirectory()) {
            return false;
        }
        boolean b = deleteDirContent(target);
        if (b) {
            return target.delete();
        }
        return false;
    }


    /**
     * 获取文件后缀名
     *
     * @param fileName 字符串
     * @return 后缀名
     */
    public static String getExtension(String fileName) {
        if (!hasExtension(fileName)) {
            return null;
        }
        return fileName.substring(fileName.lastIndexOf("."));
    }

    /**
     * 判断有没有后缀
     *
     * @param fileName 字符串
     * @return true/false
     */
    public static boolean hasExtension(String fileName) {
        if (fileName.lastIndexOf(".") == -1) {
            return false;
        }
        String endStr = fileName.substring(fileName.lastIndexOf("."));
        if (endStr.matches("^\\.[0-9a-zA-Z]+$")) {
            return true;
        }
        return false;
    }

    /**
     * 计算文件夹下的文件总数
     *
     * @param source 文件夹
     * @param count  初始数量，一般是0
     * @return 总数
     */
    public static int countFile(File source, int count) {
        // 获取源目录下的所有文件列表
        File[] files = source.listFiles();
        for (File file : files) {
            if (file.isFile()) {
                count++;
            }
            if (file.isDirectory()) {
                // 获取目标目录
                File targetFile = new File(source.getAbsolutePath() + File.separator + file.getName());
                // 递归
                count = countFile(targetFile, count);
            }
        }
        return count;
    }

    public static String getFileMD5(String filePath) {
        return Digest.fileDigest(new File(filePath), Digest.MD5);
    }

    /**
     * 解析大小为字节数，支持的单位有KB MB GB TB
     *
     * @param sizeStr 文件大小字符串
     * @return long
     */
    public static long parseSize(String sizeStr) {
        Assert.isTrue(StringUtil.hasText(sizeStr), "'sizeStr' must not be empty.");
        try {
            return Long.parseLong(sizeStr);
        } catch (NumberFormatException ignored) {
        }
        int index = sizeStr.length() - 2;
        long size = 0;
        try {
            size = Long.parseLong(sizeStr.substring(0, index));
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("size '" + sizeStr + "' unable to parse.");
        }
        String unit = sizeStr.substring(index);
        if ("kb".equalsIgnoreCase(unit)) {
            return size * 1024;
        } else if ("mb".equalsIgnoreCase(unit)) {
            return size * 1024 * 1024;
        } else if ("gb".equalsIgnoreCase(unit)) {
            return size * 1024 * 1024 * 1024;
        } else if ("tb".equalsIgnoreCase(unit)) {
            return size * 1024 * 1024 * 1024 * 1024;
        }
        throw new IllegalArgumentException("size '" + sizeStr + "' unable to parse, '" + unit + "'unit does not support.");
    }

}
